Fix Bug 30240 - std::string: append(first, last) error when aliasing. Add test cases for append/insert/assign/replace while we're at it, and fix a similar bug in insert. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@280643 91177308-0d34-0410-b5e6-96231b3b80d8 
diff --git a/include/string b/include/string index 53ddf5e..cfae0c8 100644 --- a/include/string +++ b/include/string 
@@ -1998,7 +1998,7 @@  >::type  basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)  { - basic_string __temp(__first, __last, __alloc()); + const basic_string __temp(__first, __last, __alloc());  assign(__temp.data(), __temp.size());  return *this;  } @@ -2151,11 +2151,17 @@  >::type  basic_string<_CharT, _Traits, _Allocator>::append(_InputIterator __first, _InputIterator __last)  { - basic_string __temp (__first, __last, __alloc()); + const basic_string __temp (__first, __last, __alloc());  append(__temp.data(), __temp.size());  return *this;  }   +template <typename _Tp> +bool __ptr_in_range (const _Tp* __p, const _Tp* __first, const _Tp* __last) +{ + return __first <= __p && __p < __last; +} +  template <class _CharT, class _Traits, class _Allocator>  template<class _ForwardIterator>  typename enable_if @@ -2171,13 +2177,21 @@  size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));  if (__n)  { - if (__cap - __sz < __n) - __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); - pointer __p = __get_pointer() + __sz; - for (; __first != __last; ++__p, ++__first) - traits_type::assign(*__p, *__first); - traits_type::assign(*__p, value_type()); - __set_size(__sz + __n); + if ( __ptr_in_range(&*__first, data(), data() + size())) + { + const basic_string __temp (__first, __last, __alloc()); + append(__temp.data(), __temp.size()); + } + else  + { + if (__cap - __sz < __n) + __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + pointer __p = __get_pointer() + __sz; + for (; __first != __last; ++__p, ++__first) + traits_type::assign(*__p, *__first); + traits_type::assign(*__p, value_type()); + __set_size(__sz + __n); + }  }  return *this;  } @@ -2299,7 +2313,7 @@  "string::insert(iterator, range) called with an iterator not"  " referring to this string");  #endif - basic_string __temp(__first, __last, __alloc()); + const basic_string __temp(__first, __last, __alloc());  return insert(__pos, __temp.data(), __temp.data() + __temp.size());  }   @@ -2319,11 +2333,17 @@  " referring to this string");  #endif  size_type __ip = static_cast<size_type>(__pos - begin()); - size_type __sz = size(); - size_type __cap = capacity();  size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));  if (__n)  { + if ( __ptr_in_range(&*__first, data(), data() + size())) + { + const basic_string __temp(__first, __last, __alloc()); + return insert(__pos, __temp.data(), __temp.data() + __temp.size()); + } + + size_type __sz = size(); + size_type __cap = capacity();  value_type* __p;  if (__cap - __sz >= __n)  { @@ -2523,7 +2543,7 @@  basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,  _InputIterator __j1, _InputIterator __j2)  { - basic_string __temp(__j1, __j2, __alloc()); + const basic_string __temp(__j1, __j2, __alloc());  return this->replace(__i1, __i2, __temp);  }   
diff --git a/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp index 55fc63d..8c54a38 100644 --- a/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp 
@@ -178,4 +178,21 @@  test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter()); 	}  #endif + +	{ // test appending to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.append(s_short.begin(), s_short.end()); +	assert(s_short == "123/123/"); +	s_short.append(s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/"); +	s_short.append(s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.append(s_long.begin(), s_long.end()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	} +  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp index 7c45068..e658d0f 100644 --- a/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp 
@@ -61,4 +61,20 @@  S("1234567890123456789012345678901234567890"));  }  #endif + +	{ // test appending to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.append(s_short.c_str()); +	assert(s_short == "123/123/"); +	s_short.append(s_short.c_str()); +	assert(s_short == "123/123/123/123/"); +	s_short.append(s_short.c_str()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.append(s_long.c_str()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp index 6c594eb..25a4526 100644 --- a/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp 
@@ -70,4 +70,20 @@  S("1234567890123456789012345678901234567890"));  }  #endif + +	{ // test appending to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.append(s_short.data(), s_short.size()); +	assert(s_short == "123/123/"); +	s_short.append(s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/"); +	s_short.append(s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.append(s_long.data(), s_long.size()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp index e6a5751..0d3dac7 100644 --- a/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp 
@@ -179,4 +179,21 @@  test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter()); 	}  #endif + +	{ // test assigning to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.assign(s_short.begin(), s_short.end()); +	assert(s_short == "123/"); +	s_short.assign(s_short.begin() + 2, s_short.end()); +	assert(s_short == "3/"); + +	s_long.assign(s_long.begin(), s_long.end()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/"); + +	s_long.assign(s_long.begin() + 30, s_long.end()); +	assert(s_long == "nsectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp index 386dee6..1a509e7 100644 --- a/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp 
@@ -61,4 +61,18 @@  S("12345678901234567890"));  }  #endif + +	{ // test assignment to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.assign(s_short.c_str()); +	assert(s_short == "123/"); +	s_short.assign(s_short.c_str() + 2); +	assert(s_short == "3/"); + +	s_long.assign(s_long.c_str() + 30); +	assert(s_long == "nsectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp index 0eeb926..b657127 100644 --- a/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp 
@@ -70,4 +70,20 @@  S("12345678901234567890"));  }  #endif +	{ // test assign to self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.assign(s_short.data(), s_short.size()); +	assert(s_short == "123/"); +	s_short.assign(s_short.data() + 2, s_short.size() - 2); +	assert(s_short == "3/"); + +	s_long.assign(s_long.data(), s_long.size()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/"); + +	s_long.assign(s_long.data() + 2, 8 ); +	assert(s_long == "rem ipsu"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp index bbae394..1b5baf4 100644 --- a/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp 
@@ -169,4 +169,21 @@  assert(false);  }  #endif + +	{ // test inserting into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/"); +	s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/"); +	s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.insert(s_long.begin(), s_long.begin(), s_long.end()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	} +  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp index faab5bd..3b1c2cb 100644 --- a/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp 
@@ -210,4 +210,20 @@  test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", S("can't happen"));  }  #endif + +	{ // test inserting into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.insert(0, s_short.c_str()); +	assert(s_short == "123/123/"); +	s_short.insert(0, s_short.c_str()); +	assert(s_short == "123/123/123/123/"); +	s_short.insert(0, s_short.c_str()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.insert(0, s_long.c_str()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp index 30d3df9..554b93c 100644 --- a/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp 
@@ -691,4 +691,20 @@  test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"));  }  #endif + +	{ // test inserting into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.insert(0, s_short.data(), s_short.size()); +	assert(s_short == "123/123/"); +	s_short.insert(0, s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/"); +	s_short.insert(0, s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.insert(0, s_long.data(), s_long.size()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp index cc37e79..abf1521 100644 --- a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp 
@@ -1007,4 +1007,20 @@  test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 6, TIter::TAComparison), TIter()); 	}  #endif + +	{ // test replacing into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.replace(s_long.begin(), s_long.begin(), s_long.begin(), s_long.end()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp index 730fc1a..20d185f 100644 --- a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp 
@@ -282,4 +282,20 @@  test2<S>();  }  #endif + +	{ // test replacing into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); +	assert(s_short == "123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); +	assert(s_short == "123/123/123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.replace(s_long.begin(), s_long.begin(), s_long.c_str()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  } 
diff --git a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp index 4a910e4..59d34fe 100644 --- a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp 
@@ -972,4 +972,20 @@  test8<S>();  }  #endif + +	{ // test replacing into self + typedef std::string S; +	S s_short = "123/"; +	S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + +	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); +	assert(s_short == "123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/"); +	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); +	assert(s_short == "123/123/123/123/123/123/123/123/"); + +	s_long.replace(s_long.begin(), s_long.begin(), s_long.data(), s_long.size()); +	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); +	}  }